/**
 * This console is compatible with
 * Firefox - it uses firebug console,
 * Internet Explorer 8.0 - it uses explorer's console
 * Other webbrowsers - it uses console implemented here
 * 
 * Usage:
 * 		to log: console.error("string")
 * 				console.log(Object)
 * To disable:
 * 		new Console(false)
 * To enable:
 * 		new Console(true)
 */

if (typeof(console) == "undefined") {
	function Console(isEnabled) {
		this.isEnabled = isEnabled;
		
		if (isEnabled) {
			this.windowId = "_console_window_id_" + Math.random();
			
			var head = document.getElementsByTagName("head")[0];
			
			try {
				var style = document.createElement("style");
				style.setAttribute("type", "text/css");
				style.appendChild(document.createTextNode(Console.css));
				head.appendChild(style);
			} catch (e) {
				var htmDiv = document.createElement('div');
				htmDiv.innerHTML = '<p>x</p><style type="text/css">' + Console.css + '</style>';
				head.appendChild(htmDiv.childNodes[1]);
			}
	
			this.node = document.createElement("div");
			this.node.setAttribute("id", "_console_");
			this.node.innerHTML = '<p>CONSOLE: <a href="javascript:Console.getConsole().clear();">clear</a></p>';
			this.logWindowString = '<div id="' + this.windowId + '"></div>';
			this.node.innerHTML += this.logWindowString;
			
			this.logWindow = this.node.lastChild;
			
			var onLoad = OnLoad.getOnLoad();
			onLoad.add(function() {
				var body = document.getElementsByTagName("body")[0];
				body.appendChild(con.node);
			});
		}
	}
	Console.id = "_console_";
	Console.css = "" +
		"div#" + Console.id + " {\n\t" +
			"width: 80%;\n\t" +
			"height: 200px;\n\t" +
			"border: 1px solid black;\n\t" +
			"margin: 40px auto 10px;\n\t" +
			"padding: 0px 0px 10px;\n\t" +
			"background-color: #f3e2a8;\n\t" +
			"color: black;\n\t" +
			"font-family: monospace;\n\t" +
			"font-size: 12px;\n\t" +
			"font-weight: normal;\n\t" +
			"overflow: auto;\n" +
		"}\n" +
		"div#" + Console.id + " a:link, div#" + Console.id + " a:visited {\n\t" +
			"text-decoration: none;\n\t" +
			"color: red;\n" +
		"}\n" +
		"div#" + Console.id + " a:hover {\n\t" +
			"text-decoration: underline;\n" +
		"}\n" +
		"div#" + Console.id + " p {\n\t" +
			"padding-left: 10px;\n\t" +
			"font-family: serif;\n\t" +
			"font-weight: bold;\n\t" +
			"font-size: 20px;\n" +
		"}\n" +
		"div#" + Console.id + " p a {\n\t" +
			"margin-left: 40px;\n\t" +
			"font-size: 15px;\n\t" +
			"font-weight: normal;\n" +
		"}\n" +
		"div#" + Console.id + " div div.tree {\n\t" +
			"padding-left: 10px;\n\t" +
			"margin-left: 15px;\n\t" +
			"border-left: 1px solid black;\n" +
		"}\n" +
		"div#" + Console.id + " span.ital {\n\t" +
			"font-style: italic;\n" +
		"}\n" +
		"div#" + Console.id + " span.little-font {\n\t" +
			"font-size: 10px;\n" +
		"}\n" +
		"div#" + Console.id + " span.bold {\n\t" +
			"font-weight: bold;\n" +
		"}\n" +
		"div#" + Console.id + " div div.indent {\n\t" +
			"padding-left: 40px;\n" +
		"}\n" +
		"div#" + Console.id + " div div.row {\n\t" +
			"width: 95%;\n\t" +
			"margin: 5px auto;\n\t" +
			"border-bottom: 1px solid gray;\n" +
		"";

	
	Console.prototype.clear = function() {
		this.node.removeChild(this.logWindow);
		this.node.innerHTML += this.logWindowString;
		this.logWindow = this.node.lastChild;
	}
	Console.showOrHideProperty = function(anchor) {
		var parent = anchor.parentNode.parentNode;
		var divElem = parent.getElementsByTagName("div")[0];
		var style = divElem.style;
		if (style.visibility == "hidden") {
			style.visibility = "";
			style.position = "";
			style.width = "";
			style.height = "";
			style.top = "";
			style.left = "";
		} else {
			style.visibility = "hidden";
			style.position = "absolute";
			style.width = "1px";
			style.height = "1px";
			style.top = "1px";
			style.left = "1px";
		}
	}
	Console.firstDepthOfObject = function (obj, accessedObjects, depth) {
		var boldBegin = '<span class="bold">';
		var boldEnd = '</span>';
		var output = '';
		if (typeof(obj) == "undefined") {
			return "undefined";
		} else if (obj == null) {
			return "null";
		} else if (obj.push && obj.pop) {
			output += '[';
		} else if (typeof(obj) == "object") {
			output += '{';
		}
		if (obj == window) {
			// we don't want to go into window Html element
			output += boldBegin + '<span class="ital">window</span>' + boldEnd + '; ';
		} else if (obj == document) {
			// we don't want to go into document Html element
			output += boldBegin + '<span class="ital">document</span>' + boldEnd + '; ';
		} else {
			for (var property in obj) {
				// print indentation
				output += '<div class="indent">';
				try {
					var content = obj[property];
					if (typeof(content) == "array" || typeof(content) == "object") {
						if (!accessedObjects[content]) {
							// in case, that this 'content' wasn't inspected yet, start recursion
							accessedObjects[content] = true;
							output += boldBegin + '<a href="" onclick="Console.showOrHideProperty(this); return false;">' +
								property + '</a>' + boldEnd + ': <div class="tree" style="visibility: hidden; position: absolute;">' +  Console.firstDepthOfObject(content, accessedObjects, depth + 1) + ' !! <span class="ital little-font">' + content + '</span> !!;</div> ';
						} else {
							// 'content' was inspected, thus we will display just a hint
							output += boldBegin + property + boldEnd + ': ' +  '!! <span class="ital">' + content + '</span> !!';
						}
					} else {
						if (typeof(content) == "string") {
							// if 'content' is a string, print '"' around it
							output += boldBegin + property + boldEnd + ': "' + content.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + '"; ';
						} else {
							// just print the 'content'
							output += boldBegin + property + boldEnd + ': ' + content + '; ';
						}
					}
				} catch(e) {
					// sometimes browsers add special property which aren't actyally accessible
					output += boldBegin + property + boldEnd + ': ' + '<span class="ital">denied property</span>' +'; ';
				}
				output += '</div>';
			}
		}
		if (obj.push && obj.pop) {
			output += ']';
		} else if (typeof(obj) == "object") {
			output += '}';
		}
		return output;
	}
	Console.prototype.privateWrite = function (prefix, obj) {
		if (this.isEnabled) {
			var strHead = '<div class="row">' + prefix;
			var strFoot = '</div>';
			if (typeof(obj) == "string") {
				this.logWindow.innerHTML += strHead + '"' + obj.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;") + '"' + strFoot;
			//} else if (obj.toSource) {
			//	this.logWindow.innerHTML += strHead + obj.toSource() + strFoot;
			} else {
				var accessedObjects = [];
				this.logWindow.innerHTML += strHead + Console.firstDepthOfObject(obj, accessedObjects, 1) + strFoot;
			}
		}
	};
	Console.prototype.log = function (obj) {
		this.privateWrite("[LOG]&nbsp;&nbsp;&nbsp;|&nbsp;", obj);
	};
	Console.prototype.error = function (obj) {
		this.privateWrite("[ERROR]&nbsp;|&nbsp;", obj);
	};
	Console.getConsole = function() {
		if (typeof(con) == "undefined" || con == null || con == undefined) {
			con = new Console();
		}
		return con;
	};
	var con = new Console(false);
	console = con;
} else {
	var con = console;
}

if (window.onerror) {
	window.onerror = function(msg, url, l) {
		con.error('error: ' + msg + '<br/>line: ' + l + '<br/>' + url);
	}
}